/*******************************************************************************************
*
*   Projectile Motion Simulator using raylib
*   一个使用 raylib 模拟平抛运动的小程序
*
*   Features:
*   - Fixed camera view.
*   - Launch balls with spacebar.
*   - Aim using mouse click to define initial velocity vector.
*   - Balls follow parabolic trajectory under gravity.
*   - Trajectory is visualized with random semi-transparent colored trails.
*   - Visualized initial velocity vector with angle and magnitude display.
*
********************************************************************************************/

#include "raylib.h"
#include "raymath.h"
#include <vector>   // 用于 std::vector 容器
#include <cstdlib>  // 用于 rand() 和 srand() 函数 (随机数)
#include <ctime>    // 用于 time() 函数 (获取时间，用作随机数种子)
#include <cmath>    // 用于 atan2f, sqrtf (虽然 Vector2Length 内部会用)

//----------------------------------------------------------------------------------
// 常量定义 (Defines)
//----------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 600;
const float GRAVITY = 98.0f;          // 重力加速度 (像素/秒^2), 正值向下
const Vector2 launchPosition = { 50.0f, screenHeight - 50.0f }; // 固定发射点 (屏幕左下角)
const float BALL_RADIUS = 8.0f;       // 小球半径
const float VELOCITY_SCALE_FACTOR = 1.0f; // 速度缩放因子 (鼠标拖拽距离到初速度的转换比例)
const int MAX_TRAIL_POINTS = 300;     // 每个小球轨迹点的最大数量
const float VELOCITY_ARROW_SCALE_FACTOR = 1.0f; // 新增：用于绘制小球瞬时速度箭头的缩放因子

//----------------------------------------------------------------------------------
// 结构体定义 (Structures)
//----------------------------------------------------------------------------------
// 小球结构体
typedef struct Ball {
    Vector2 position;                   // 当前位置
    Vector2 velocity;                   // 当前速度 (x分量, y分量)
    Color trailColor;                   // 轨迹颜色
    std::vector<Vector2> trailPoints;   // 存储轨迹点的向量
    bool active;                        // 小球是否活动 (用于未来可能的优化，如移除屏幕外的小球)
} Ball;

//----------------------------------------------------------------------------------
// 全局变量 (Global Variables)
//----------------------------------------------------------------------------------
std::vector<Ball> balls; // 存储所有小球的动态数组 (vector)
Vector2 aimPoint;        // 鼠标点击设置的瞄准点
bool aimPointSet = false; // 标记瞄准点是否已设置
bool showVelocityVectors = false; // 标记是否显示小球的速度矢量
bool isPaused = false; // 新增：标记游戏是否暂停

//----------------------------------------------------------------------------------
// 函数声明 (Function Declarations)
//----------------------------------------------------------------------------------
void LaunchNewBall(Vector2 initialVelocity); // 发射新小球的函数
void UpdateActiveBalls(float deltaTime);     // 更新所有活动小球状态的函数
void DrawSimulation();                       // 绘制整个模拟场景的函数
void DrawAimingAssistance();                 // 绘制瞄准辅助线的函数
void DrawBallTrails();                       // 绘制小球轨迹的函数
void DrawVectorArrow(Vector2 start, Vector2 end, float thickness, Color color); // 新增：绘制矢量箭头

//------------------------------------------------------------------------------------
// 程序主入口点 (Program main entry point)
//------------------------------------------------------------------------------------
int main(void)
{
    // 初始化 (Initialization)
    //--------------------------------------------------------------------------------------
    InitWindow(screenWidth, screenHeight, "Projectile Motion Simulator - raylib");
    SetTargetFPS(60); // 设置目标每秒帧数

    srand(time(NULL)); // 初始化随机数生成器种子，确保每次运行的随机颜色不同

    aimPoint = launchPosition; // 初始时，可以将瞄准点设为发射点或屏幕中心
    //--------------------------------------------------------------------------------------

    // 主游戏循环 (Main game loop)
    while (!WindowShouldClose()) // 检测窗口是否应关闭 (如用户点击关闭按钮或按 ESC)
    {
        // 更新逻辑 (Update)
        //----------------------------------------------------------------------------------
        float deltaTime = GetFrameTime(); // 获取上一帧所花费的时间

        // 处理用户输入 (Handle Input)
        if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) // 如果鼠标左键被持续按下
        {
            aimPoint = GetMousePosition(); // 获取当前鼠标位置作为瞄准点
            aimPointSet = true;            // 标记瞄准点已设置
        }

        if (IsKeyPressed(KEY_SPACE) && aimPointSet) // 如果空格键被按下且瞄准点已设置
        {
            // 计算初始速度矢量：从发射点指向瞄准点
            Vector2 initialVelocityDirection = Vector2Subtract(aimPoint, launchPosition);
            // 根据缩放因子调整初始速度大小
            Vector2 initialVelocity = Vector2Scale(initialVelocityDirection, VELOCITY_SCALE_FACTOR);
            LaunchNewBall(initialVelocity); // 发射新小球
        }

        if (IsKeyPressed(KEY_D)) 
        {
            showVelocityVectors = !showVelocityVectors; 
        }

        if (IsKeyPressed(KEY_P)) // 新增：处理 'P' 键按下事件
        {
            isPaused = !isPaused; // 切换暂停状态
        }

        if (!isPaused) // 新增：仅在未暂停时更新小球状态
        {
            UpdateActiveBalls(deltaTime); // 更新所有小球的状态
        }
        //----------------------------------------------------------------------------------

        // 绘制阶段 (Draw)
        //----------------------------------------------------------------------------------
        BeginDrawing(); // 开始绘制

            ClearBackground(RAYWHITE); // 用浅白色清空背景

            DrawSimulation(); // 绘制模拟场景内容

            // 绘制UI提示文字 (已修改为英文)
            DrawText("Left-click and drag to set aim point", 10, 10, 20, DARKGRAY); 
            DrawText("Press SPACE to launch ball", 10, 40, 20, DARKGRAY);
            if (aimPointSet)
            {
                DrawText(TextFormat("Aim Point: (%.0f, %.0f)", aimPoint.x, aimPoint.y), 10, 70, 15, GRAY);
                
                Vector2 velDirUnscaled = Vector2Subtract(aimPoint, launchPosition);
                Vector2 actualInitialVelocity = Vector2Scale(velDirUnscaled, VELOCITY_SCALE_FACTOR);
                float magnitude = Vector2Length(actualInitialVelocity);
                
                float angleRadians = atan2f(launchPosition.y - aimPoint.y, aimPoint.x - launchPosition.x);
                float angleDegrees = angleRadians * RAD2DEG;

                DrawText(TextFormat("Est. Initial Velocity: <%.1f, %.1f>", actualInitialVelocity.x, actualInitialVelocity.y), 10, 95, 15, GRAY);
                DrawText(TextFormat("Angle: %.1f degrees", angleDegrees), 10, 120, 15, DARKGREEN);
                DrawText(TextFormat("Magnitude (Speed): %.1f pixels/sec", magnitude), 10, 145, 15, DARKGREEN);
            }
            
            DrawText(TextFormat("Show Velocity Vectors (D): %s", showVelocityVectors ? "ON" : "OFF"), 10, 170, 15, DARKBLUE);
            DrawText(TextFormat("Pause (P): %s", isPaused ? "ON" : "OFF"), 10, 195, 15, DARKBLUE); // 新增：显示暂停状态的提示文字


        EndDrawing(); // 结束绘制
        //----------------------------------------------------------------------------------
    }

    // 反初始化/清理 (De-Initialization)
    //--------------------------------------------------------------------------------------
    CloseWindow();        // 关闭窗口并释放OpenGL上下文
    //--------------------------------------------------------------------------------------

    return 0;
}

//----------------------------------------------------------------------------------
// 函数定义 (Function Definitions)
//----------------------------------------------------------------------------------

// 新增：绘制矢量箭头的函数
void DrawVectorArrow(Vector2 start, Vector2 end, float thickness, Color color)
{
    // 如果起点和终点太近，则不绘制箭头，避免视觉混乱
    if (Vector2Distance(start, end) < 1.0f) return;

    DrawLineEx(start, end, thickness, color);

    // 箭头头部参数
    float arrowHeadLength = 12.0f;
    float arrowHeadAngle = 25.0f; // 箭头翼与主线的夹角 (度)

    Vector2 direction = Vector2Normalize(Vector2Subtract(end, start));

    // 计算箭头翼的两个点
    Vector2 wing1End = Vector2Add(end, Vector2Rotate(Vector2Scale(direction, -arrowHeadLength), -arrowHeadAngle * DEG2RAD));
    Vector2 wing2End = Vector2Add(end, Vector2Rotate(Vector2Scale(direction, -arrowHeadLength), arrowHeadAngle * DEG2RAD));
    
    DrawLineEx(end, wing1End, thickness, color);
    DrawLineEx(end, wing2End, thickness, color);

    // 或者使用三角形绘制箭头头部 (另一种风格)
    /*
    float arrowHeadSize = thickness * 5;
    Vector2 direction = Vector2Normalize(Vector2Subtract(end, start));
    Vector2 p1 = end;
    Vector2 p2 = Vector2Add(Vector2Subtract(end, Vector2Scale(direction, arrowHeadSize)), Vector2Scale((Vector2){-direction.y, direction.x}, arrowHeadSize / 2.5f));
    Vector2 p3 = Vector2Add(Vector2Subtract(end, Vector2Scale(direction, arrowHeadSize)), Vector2Scale((Vector2){direction.y, -direction.x}, arrowHeadSize / 2.5f));
    DrawTriangle(p1, p2, p3, color);
    */
}

// 发射新小球的函数
void LaunchNewBall(Vector2 initialVelocity)
{
    Ball newBall;
    newBall.position = launchPosition; // 初始位置为发射点
    newBall.velocity = initialVelocity; // 设置初始速度
    // 生成随机的半透明颜色用于轨迹
    newBall.trailColor = (Color){
        (unsigned char)GetRandomValue(50, 200),  // R
        (unsigned char)GetRandomValue(50, 200),  // G
        (unsigned char)GetRandomValue(50, 200),  // B
        150                                      // Alpha (150/255 透明度)
    };
    newBall.active = true; // 标记为活动状态
    newBall.trailPoints.clear(); // 清空之前的轨迹点 (如果是复用对象)
    newBall.trailPoints.push_back(newBall.position); // 将发射点作为轨迹的第一个点
    balls.push_back(newBall); // 将新小球添加到全局的小球向量中
}

// 更新所有活动小球状态的函数
void UpdateActiveBalls(float deltaTime)
{
    for (size_t i = 0; i < balls.size(); ++i) // C++风格的for循环遍历vector
    {
        if (balls[i].active)
        {
            // 应用重力 (只影响y轴速度)
            balls[i].velocity.y += GRAVITY * deltaTime;

            // 根据速度更新位置
            // position = position + velocity * deltaTime
            balls[i].position = Vector2Add(balls[i].position, Vector2Scale(balls[i].velocity, deltaTime));

            // 添加当前位置到轨迹点列表
            if (balls[i].trailPoints.size() < MAX_TRAIL_POINTS)
            {
                balls[i].trailPoints.push_back(balls[i].position);
            }
            // 可选: 如果轨迹点过多，可以移除旧的点，形成固定长度的尾巴
            // else {
            //     balls[i].trailPoints.erase(balls[i].trailPoints.begin());
            //     balls[i].trailPoints.push_back(balls[i].position);
            // }

            // 简单边界检测：如果小球飞出屏幕太远，可以考虑将其标记为不活动
            // (为了教学目的，暂时让它们一直飞，以便观察完整轨迹)
            // if (balls[i].position.y > screenHeight + BALL_RADIUS * 10 ||
            //     balls[i].position.x < -BALL_RADIUS * 10 ||
            //     balls[i].position.x > screenWidth + BALL_RADIUS * 10)
            // {
            //     balls[i].active = false;
            // }
        }
    }

    // 可选: 移除不活动的小球以优化性能 (如果实现了active标记的改变)
    // balls.erase(std::remove_if(balls.begin(), balls.end(), [](const Ball& b){ return !b.active; }), balls.end());
}

// 绘制整个模拟场景的函数
void DrawSimulation()
{
    // 绘制地面线 (水平线在发射点y坐标处)
    DrawLine(0, (int)launchPosition.y, screenWidth, (int)launchPosition.y, DARKGRAY);

    // 绘制发射点标记
    DrawCircleV(launchPosition, 5, DARKBLUE);

    // 绘制瞄准辅助线
    DrawAimingAssistance();

    // 绘制所有小球的轨迹
    DrawBallTrails();

    // 绘制所有活动的小球
    for (const auto& ball : balls) // C++11 范围for循环 (只读访问)
    {
        if (ball.active)
        {
            DrawCircleV(ball.position, BALL_RADIUS, MAROON); // 用深红色绘制小球

            // 新增：如果开启了显示速度矢量模式，则绘制速度矢量
            if (showVelocityVectors)
            {
                Vector2 pos = ball.position;
                Vector2 vel = ball.velocity;

                // 绘制总的瞬时速度矢量 (蓝色)
                Vector2 totalVelEnd = Vector2Add(pos, Vector2Scale(vel, VELOCITY_ARROW_SCALE_FACTOR));
                DrawVectorArrow(pos, totalVelEnd, 1.5f, BLUE);

                // 绘制水平速度分量矢量 (红色)
                Vector2 horizontalVel = { vel.x, 0.0f };
                Vector2 horizontalVelEnd = Vector2Add(pos, Vector2Scale(horizontalVel, VELOCITY_ARROW_SCALE_FACTOR));
                DrawVectorArrow(pos, horizontalVelEnd, 1.5f, RED);

                // 绘制垂直速度分量矢量 (绿色)
                Vector2 verticalVel = { 0.0f, vel.y };
                Vector2 verticalVelEnd = Vector2Add(pos, Vector2Scale(verticalVel, VELOCITY_ARROW_SCALE_FACTOR));
                DrawVectorArrow(pos, verticalVelEnd, 1.5f, GREEN);
            }
        }
    }
}

// 绘制瞄准辅助线的函数
void DrawAimingAssistance()
{
    if (aimPointSet) // 仅当瞄准点被设置后才绘制
    {
        // 从发射点到瞄准点绘制一条代表初速度的矢量箭头
        DrawVectorArrow(launchPosition, aimPoint, 2.0f, BLUE);
        // 在瞄准点位置绘制一个小圆圈标记
        DrawCircleV(aimPoint, 5, GRAY);
    }
}

// 绘制小球轨迹的函数
void DrawBallTrails()
{
    for (const auto& ball : balls)
    {
        if (ball.active && ball.trailPoints.size() > 1)
        {
            // 遍历轨迹点，绘制小圆点形成轨迹
            for (size_t i = 0; i < ball.trailPoints.size(); ++i)
            {
                DrawCircleV(ball.trailPoints[i], 2.0f, ball.trailColor); // 用轨迹颜色绘制小圆点
            }
            // 或者，可以绘制连接轨迹点的线段：
            // for (size_t i = 0; i < ball.trailPoints.size() - 1; ++i)
            // {
            //    DrawLineEx(ball.trailPoints[i], ball.trailPoints[i+1], 2.0f, ball.trailColor);
            // }
        }
    }
}